package com.zrt.springboot.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zrt.springboot.common.Result;
import com.zrt.springboot.controller.dto.RiverDTO;
import com.zrt.springboot.controller.dto.UserDTO;
import com.zrt.springboot.entity.EmailAndSensorId;
import com.zrt.springboot.entity.River;
import com.zrt.springboot.entity.User;
import com.zrt.springboot.mapper.SensorRegisteredMapper;
import com.zrt.springboot.service.CreateRiverDataService;
import com.zrt.springboot.service.IRiverService;
import com.zrt.springboot.utils.LimitedQueue;
import com.zrt.springboot.utils.Simulated;
import com.zrt.springboot.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/createRiverData")
public class CreateRiverDataController {
    @Autowired
    private SensorRegisteredMapper sensorRegisteredMapper;

    static LimitedQueue<Double> limitedQueue = new LimitedQueue<>(6);
    static LimitedQueue<Double> limitedQueue2 = new LimitedQueue<>(6);
    static LimitedQueue<Double> limitedQueue3 = new LimitedQueue<>(6);
    static LimitedQueue<Double> limitedQueue4 = new LimitedQueue<>(6);

    @Autowired
    private Simulated simulated;

    @Autowired
    private IRiverService riverService;

    @PostMapping("/import")
    public Result imp(MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        // 方式2：忽略表头的中文，直接读取表的内容
        List<List<Object>> list = reader.read(1);
        List<River> rivers = CollUtil.newArrayList();
        for (List<Object> row : list) {
            River river = new River(row.get(1).toString(),Double.parseDouble(row.get(2).toString()) ,row.get(3).toString());
            rivers.add(river);
        }
        riverService.saveBatch(rivers);
        return Result.success(true);
    }

    @GetMapping("/export")
    public void export(HttpServletResponse response) throws Exception {
        // 从数据库查询出所有的数据
        List<River> list = riverService.list();
        // 通过工具类创建writer 写出到磁盘路径
//        ExcelWriter writer = ExcelUtil.getWriter(filesUploadPath + "/用户信息.xlsx");
        // 在内存操作，写出到浏览器
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //自定义标题别名
        writer.addHeaderAlias("id", "序列号");
        writer.addHeaderAlias("sensorId", "传感器id");
        writer.addHeaderAlias("depth", "河流水位(m)");
        writer.addHeaderAlias("time", "时间");

        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(list, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("河流水位报表", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();

    }

    @GetMapping("/exportAppoint")
    public void exportAppoint(@RequestParam long startDateAndTime,
                                @RequestParam long endDateAndTime,
                                @RequestParam String sensorId ) throws Exception {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = format.format(startDateAndTime);
        String endTime = format.format(endDateAndTime);
        QueryWrapper<River> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sensor_id",sensorId).between("time",startTime,endTime);
        // 从数据库查询出指定的数据
        List<River> list = riverService.list(queryWrapper);
        // 通过工具类创建writer 写出到磁盘路径
//        ExcelWriter writer = ExcelUtil.getWriter(filesUploadPath + "/用户信息.xlsx");
        // 在内存操作，写出到浏览器
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //自定义标题别名
        writer.addHeaderAlias("id", "序列号");
        writer.addHeaderAlias("sensorId", "传感器id");
        writer.addHeaderAlias("depth", "河流水位(m)");
        writer.addHeaderAlias("time", "时间");

        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(list, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("河流水位报表", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();
        //return Result.success();
    }

    @PostMapping("/del/batch")
    public Result deleteBatch(@RequestBody List<Integer> ids) {
        return Result.success(riverService.removeByIds(ids));
    }

    @Autowired
    private CreateRiverDataService createRiverDataService;

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        return Result.success(riverService.removeById(id));
    }

    @PostMapping
    public Result save(@RequestBody River river) {
        boolean flag = riverService.saveOrUpdate(river);
        return Result.success(flag);
    }

    @GetMapping("/all")
    public Result findAll( @RequestParam Integer pageNum,
                           @RequestParam Integer pageSize) {
        Page<River> page = riverService.page(new Page<>(pageNum, pageSize));
        return Result.success(page);
    }

    @GetMapping("/page")
    public Result findPage(@RequestParam Integer pageNum,
                           @RequestParam Integer pageSize,
                           @RequestParam long startDateAndTime,
                           @RequestParam long endDateAndTime,
                           @RequestParam String sensorId)  {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = format.format(startDateAndTime);
        String endTime = format.format(endDateAndTime);
        if (startDateAndTime == 0 && endDateAndTime == 0 && "".equals(sensorId)){
            Page<River> page = riverService.page(new Page<>(pageNum, pageSize));
            return Result.success(page);
        }else {
            QueryWrapper<River> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("sensor_id",sensorId).between("time",startTime,endTime);
            Page<River> page = riverService.page(new Page<>(pageNum, pageSize), queryWrapper);
            return Result.success(page);
        }

    }

    @GetMapping("/selectDataByTimeAndId")
    public Result selectDataByTimeAndId(@RequestParam long startDateAndTime,
                                        @RequestParam long endDateAndTime,
                                        @RequestParam String sensorId){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = format.format(startDateAndTime);
        String endTime = format.format(endDateAndTime);
        List<String> timeList = riverService.selectTime(sensorId,startTime,endTime);
        List<Double> dataList = riverService.selectTheData(sensorId, startTime, endTime);
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("time",timeList);
        map.put("data",dataList);
        return Result.success(map);
    }

    @GetMapping("/getMaxAndMinData")
    public Result getMaxAndMinData( @RequestParam String sensorId){
        double max = sensorRegisteredMapper.selectMax(sensorId);
        double min = sensorRegisteredMapper.selectMin(sensorId);
        RiverDTO riverDTO = new RiverDTO(max,min);
        return Result.success(riverDTO);
    }

    @GetMapping("/total")
    public Result total(@RequestParam String email,
                        @RequestParam String sensorId) throws InterruptedException {
        Map<String, Object> map = execute(limitedQueue,sensorId,email);
//        Thread.sleep(1000);
        return Result.success(map);
    }

    @GetMapping("/total2")
    public Result total2(@RequestParam String email,
                        @RequestParam String sensorId) throws InterruptedException {
        Map<String, Object> map = execute(limitedQueue2,sensorId,email);
        return Result.success(map);
    }

    @GetMapping("/total3")
    public Result total3(@RequestParam String email,
                        @RequestParam String sensorId) throws InterruptedException {
        Map<String, Object> map = execute(limitedQueue3,sensorId,email);
        return Result.success(map);
    }

    @GetMapping("/total4")
    public Result total4(@RequestParam String email,
                        @RequestParam String sensorId) throws InterruptedException {
        Map<String, Object> map = execute(limitedQueue4,sensorId,email);
        return Result.success(map);
    }


    public Map<String,Object> execute(LimitedQueue<Double> limitedQueue,String sensorId,String email) throws InterruptedException {
        //获得当前的时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long times = System.currentTimeMillis();

        //随机生成河流深度数据
        River r1 = simulated.RiverMonitorBySensorId(sensorId);

        //将当前时间赋值给河流的时间属性
        r1.setTime(format.format(times));
        //根据注册表查询当前选择的传感器的阈值，如果大于或者小于阈值，则发送邮件
        boolean flag = createRiverDataService.simulateDataBySensorId(email, r1);
        //将数据写入数据库
        riverService.save(r1);

        Map<String, Object> map = new HashMap<>();

        limitedQueue.add(r1.getDepth());

        ArrayList<String> strings = CollUtil.newArrayList(format.format(times),format.format(times+1000),format.format(times+2000),
                format.format(times+3000),format.format(times+4000),format.format(times+5000));
        ArrayList<Double> doubles = CollUtil.newArrayList(limitedQueue.get(0),limitedQueue.get(1),limitedQueue.get(2),
                limitedQueue.get(3),limitedQueue.get(4),limitedQueue.get(5));
        System.out.println(doubles);
        map.put("timeList",strings);
        map.put("dataList",doubles);
        map.put("flag",flag);
        return map;
    }

    @GetMapping("/showOneData")
    public Result showOneData(@RequestParam String email,
                              @RequestParam String sensorId) throws InterruptedException {
        //随机生成河流深度数据
        River r1 = simulated.RiverMonitorBySensorId(sensorId);
        //获得当前的时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long times = System.currentTimeMillis();
        //将当前时间赋值给河流的时间属性
        r1.setTime(format.format(times));
        //根据注册表查询当前选择的传感器的阈值，如果大于或者小于阈值，则发送邮件
        boolean flag = createRiverDataService.simulateDataBySensorId(email, r1);
        //将数据写入数据库
        riverService.save(r1);

        limitedQueue.add(r1.getDepth());

        //创建一个map集合，键值对存储时间和河流深度的数据
        Map<String, Object> map = new HashMap<>();
        ArrayList<String> strings = CollUtil.newArrayList(format.format(times),format.format(times+1000),format.format(times+2000),
                format.format(times+3000),format.format(times+4000),format.format(times+5000));
        ArrayList<Double> doubles = CollUtil.newArrayList(limitedQueue.get(0),limitedQueue.get(1),limitedQueue.get(2),
                limitedQueue.get(3),limitedQueue.get(4),limitedQueue.get(5));
        System.out.println(doubles);
        map.put("timeList",strings);
        map.put("dataList",doubles);
        map.put("flag",flag);
        //创建result对象返回前端
        return Result.success(map);
    }


}
